package com.zhouhx.flow.tasklist.entity;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import com.zhouhx.flow.tasklist.TaskState;
import com.zhouhx.flow.tasklist.enums.FlowStepStatusEnum;
import com.zhouhx.flow.tasklist.enums.FlowStepTypeEnum;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Date;
import java.util.function.Function;

/**
 * @author : zhouhx
 * 流程步骤
 * @date : 2024/5/3 14:50
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public  class FlowStep implements TaskState {
    private static final Logger log = LoggerFactory.getLogger(FlowStep.class);
    /**
     * 流程步骤id(必填)
     */
    private String flowStepId;
    /**
     * 获取状态的方法(必填),返回值是定义的流程状态
     */
    private Function<String,?> stateFunction;
    /**
     * 执行动作的方法(必填),返回值是定义的流程状态
     */
    private Function<String,?> excuteFunction;
    /**
     * 下一个流程步骤id(必填)
     */
    private String nextFlowStepId;
    /**
     * 步骤类型(必填)
     */
    private String stepType;
    /**
     * 执行次数
     */
    private int count;
    /**
     * 步骤名称
     */
    private String flowStepName;
    /**
     * 创建时间(格式：yyyy-MM-dd HH:mm:ss.SSSS)
     */
    private String createdTime;
    /**
     * 结束时间(格式：yyyy-MM-dd HH:mm:ss.SSSS)
     */
    private String endTime;
    /**
     * 步骤状态
     */
    private Integer flowStepStatus;

    /**
     * 执行动作的方法的返回状态
     */
    private String excuteFunctionStatus;
    /**
     * 执行动作的方法的错误原因
     */
    private String errorMsg;

    @Override
    public String getState(String equipmentNo) {
        if(ObjectUtil.isNotEmpty(stateFunction)){
            Object apply = stateFunction.apply(equipmentNo);

            return apply.toString();
        }

        return null;
    }

    @Override
    public void execute(String equipmentNo) {
        if(ObjectUtil.isEmpty(excuteFunction)){
            return;
        }
        this.createdTime = DateUtil.format(new Date(), DatePattern.NORM_DATETIME_MS_PATTERN);
        this.flowStepStatus = FlowStepStatusEnum.RUNNING.getStatus();
        // 执行方法可能报错，放在最后
        try {
            Object apply = excuteFunction.apply(equipmentNo);
            this.excuteFunctionStatus = apply.toString();
        } catch (Exception e) {
            log.error("流程任务>>>>>>执行流程步骤【{}】异常",flowStepName,e);
            this.errorMsg = e.getMessage();
        }
    }

    public void check(){
        Assert.notNull(this.flowStepId,"流程步骤id不能为null");
        Assert.notNull(this.stepType," 步骤类型不能为null");
        // 结束步骤不判断
        if(!this.stepType.equals(FlowStepTypeEnum.END.getType())){
            Assert.notNull(this.stateFunction,"获取状态的方法不能为null");
            Assert.notNull(this.excuteFunction,"获取执行动作的方法不能为null");
            Assert.notNull(this.nextFlowStepId,"下一个流程步骤id不能为null");
        }
    }
}
